1 /*
2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021
3 License:   [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License].
4 Authors: Marcelo S. N. Mancini
5 
6 	Copyright Marcelo S. N. Mancini 2018 - 2021.
7 Distributed under the CC BY-4.0 License.
8    (See accompanying file LICENSE.txt or copy at
9 	https://creativecommons.org/licenses/by/4.0/
10 */
11 module hip.image;
12 public import hip.api.data.image;
13 
14 
15 IHipBMPDecoder bmp;
16 IHipJPEGDecoder jpeg;
17 IHipPNGDecoder png;
18 IHipWebPDecoder webP;
19 
20 
21 public class HipImageImpl : IImage
22 {
23     IHipImageDecoder decoder;
24     string imagePath;
25     int width, height;
26     ubyte bytesPerPixel;
27     ushort bitsPerPixel;
28     
29     ubyte[] pixels;
30     this(string path = "")
31     {
32         import hip.image_backend.impl;
33         imagePath = path;
34         decoder = getDecoder(path);
35     }
36 
37     static immutable(IImage) getPixelImage()
38     {
39         __gshared HipImageImpl img; 
40         __gshared ubyte[4] pixel = IHipImageDecoder.getPixel();
41         if(img is null)
42         {
43             img = new HipImageImpl("Pixel");
44             img.pixels = pixel;
45             img.width = 1;
46             img.height = 1;
47             img.bytesPerPixel = 4;
48         }
49         return cast(immutable)img;
50     }
51     string getName() const {return imagePath;}
52     uint getWidth() const {return width;}
53     uint getHeight() const {return height;}
54     ubyte getBytesPerPixel() const {return bytesPerPixel;}
55     const(ubyte[]) getPalette() const {return decoder.getPalette;}
56     const(ubyte[]) getPixels() const {return pixels;}
57 
58     void loadRaw(in ubyte[] pixels, int width, int height, ubyte bytesPerPixel)
59     {
60         this.width = width;
61         this.height = height;
62         this.pixels = cast(ubyte[])pixels;
63         this.bytesPerPixel = bytesPerPixel;
64         this.bitsPerPixel = cast(ubyte)(bytesPerPixel*8);
65     }
66 
67 
68     bool loadFromMemory(ubyte[] data, void delegate(IImage self) onSuccess, void delegate() onFailure)
69     {
70         import hip.error.handler;
71         if(ErrorHandler.assertErrorMessage(data.length != 0, "No data was passed to load Image.", "Could not load image"))
72             return false;
73         if(ErrorHandler.assertLazyErrorMessage(decoder.startDecoding(data, ()
74         {
75             width         = decoder.getWidth();
76             height        = decoder.getHeight();
77             bitsPerPixel  = decoder.getBitsPerPixel();
78             bytesPerPixel = decoder.getBytesPerPixel();
79             pixels        = cast(ubyte[])decoder.getPixels();
80             onSuccess(this);
81         }, onFailure),
82         "Decoding Image: ", "Could not load image " ~ imagePath))
83             return false;
84         
85         return true;
86     }
87 
88     bool hasLoadedData() const {return pixels !is null && width != 0 && height != 0;}
89 
90     ubyte[] monochromeToRGBA() const
91     {
92         import hip.error.handler;
93         ubyte[] pix = new ubyte[](4*width*height); //RGBA for each pixel
94         ErrorHandler.assertExit(pix != null, "Out of memory when converting monochrome to RGBA");
95         uint pixelsLength = width*height;
96         ubyte color;
97         uint z;
98         for(uint i = 0; i < pixelsLength; i++)
99         {
100             //Palette r color = palette[pixels[i]*4]
101             color = (cast(ubyte*)pixels)[i];
102             pix[z++] = color; //R
103             pix[z++] = color; //G
104             pix[z++] = color; //B
105             pix[z++] = color; //A
106         }
107 
108         return pix;
109     }
110 
111     ubyte[] convertPalettizedToRGBA() const
112     {
113         import hip.error.handler;
114         ubyte[] pix = new ubyte[](4*width*height); //RGBA for each pixel
115         ErrorHandler.assertExit(pix != null, "Out of memory when converting palette pixels to RGBA");
116 
117         uint pixelsLength = width*height;
118         const(ubyte[]) palette = decoder.getPalette();
119 
120         uint colorIndex;
121         uint z;
122         for(uint i = 0; i < pixelsLength; i++)
123         {
124             //Palette r color = palette[pixels[i]*4]
125             colorIndex = (cast(ubyte*)pixels)[i]*4;
126             pix[z++]   = palette[colorIndex]; //R
127             pix[z++] = palette[colorIndex+1]; //G
128             pix[z++] = palette[colorIndex+2]; //B
129             pix[z++] = palette[colorIndex+3]; //A
130         }
131 
132         return pix;
133     }
134 
135     void dispose()
136     {
137         decoder.dispose();
138     }
139     alias w = width;
140     alias h = height;
141 }
142 
143